package com.alibaba.gaiax.demo.zdm

import android.content.Intent
import android.text.TextUtils
import android.widget.Toast
import com.alibaba.fastjson.JSON
import com.alibaba.fastjson.JSONArray
import com.alibaba.fastjson.JSONObject
import com.alibaba.gaiax.demo.ZDMTemplateActivity
import com.alibaba.gaiax.demo.utils.FileUtil
import com.google.zxing.Result
import com.king.zxing.CameraScan
import com.king.zxing.CaptureActivity
import com.king.zxing.DecodeConfig
import com.king.zxing.DecodeFormatManager
import com.king.zxing.analyze.MultiFormatAnalyzer
import okhttp3.Call
import okhttp3.Callback
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import java.io.IOException


class ZQRCodeActivity : CaptureActivity() {

    override fun initCameraScan() {
        super.initCameraScan()

        //初始化解码配置
        val decodeConfig = DecodeConfig()
        decodeConfig.setHints(DecodeFormatManager.QR_CODE_HINTS) //如果只有识别二维码的需求，这样设置效率会更高，不设置默认为DecodeFormatManager.DEFAULT_HINTS
            .setFullAreaScan(false) //设置是否全区域识别，默认false
            .setAreaRectRatio(0.8f) //设置识别区域比例，默认0.8，设置的比例最终会在预览区域裁剪基于此比例的一个矩形进行扫码识别
            .setAreaRectVerticalOffset(0).areaRectHorizontalOffset =
            0 //设置识别区域水平方向偏移量，默认为0，为0表示居中，可以为负数

        //在启动预览之前，设置分析器，只识别二维码
        cameraScan
            .setVibrate(true) //设置是否震动，默认为false
            .setNeedAutoZoom(true) //二维码太小时可自动缩放，默认为false
            .setAnalyzer(MultiFormatAnalyzer(decodeConfig)) //设置分析器,如果内置实现的一些分析器不满足您的需求，你也可以自定义去实现
    }


    /**
     * 扫码结果回调
     * @param result
     * @return 返回false表示不拦截，将关闭扫码界面并将结果返回给调用界面；
     * 返回true表示拦截，需自己处理逻辑。当isAnalyze为true时，默认会继续分析图像（也就是连扫）。
     * 如果只是想拦截扫码结果回调，并不想继续分析图像（不想连扫），请在拦截扫码逻辑处通过调
     * 用[CameraScan.setAnalyzeImage]，
     * 因为[CameraScan.setAnalyzeImage]方法能动态控制是否继续分析图像。
     */
    override fun onScanResultCallback(result: Result?): Boolean {
        /*
         * 因为setAnalyzeImage方法能动态控制是否继续分析图像。
         *
         * 1. 因为分析图像默认为true，如果想支持连扫，返回true即可。
         * 当连扫的处理逻辑比较复杂时，请在处理逻辑前调用getCameraScan().setAnalyzeImage(false)，
         * 来停止分析图像，等逻辑处理完后再调用getCameraScan().setAnalyzeImage(true)来继续分析图像。
         *
         * 2. 如果只是想拦截扫码结果回调自己处理逻辑，但并不想继续分析图像（即不想连扫），可通过
         * 调用getCameraScan().setAnalyzeImage(false)来停止分析图像。
         */

        val client = OkHttpClient()

        val getRequest = result?.let {
            Request.Builder()
                .url(it.text)
                .build()
        }
        try {
            getRequest?.let {
                client.newCall(it).enqueue(object : Callback {
                    override fun onFailure(call: Call, e: IOException) {
                        Toast.makeText(baseContext, e.message, Toast.LENGTH_SHORT).show()
                    }

                    override fun onResponse(call: Call, response: Response) {
                        val responseBody = response.body?.string()
                        if (responseBody != null) {
                            jsonToGaixaFile(responseBody)
                        }
                    }

                })
            }
        } catch (e: IOException) {
            e.printStackTrace()
        }
        return super.onScanResultCallback(result)
    }

    fun jsonToGaixaFile(jsonBody: String) {
        val json = JSON.parseObject(jsonBody)
        val content = json.getJSONObject("data").getString("content");
        val contentJSON = JSON.parseObject(content);
        val pkg = contentJSON.getJSONObject("package")
        val layers = contentJSON.getJSONArray("layers")
        val id = pkg.getString("id");
        val type = contentJSON.getString("type");
        val styles = contentJSON.getString("styles")
        val indexCss = StringBuilder("#$id{\n");
        val data = contentJSON.getJSONObject("data");

        indexCss.append(styles + "\n");
        indexCss.append("}\n");

        val indexDatabingding = StringBuilder("");
        val indexData = StringBuilder("");
        val indexJson = StringBuilder("");
        val layersJson = StringBuilder("");

        parseLayers(layers, indexCss, indexData, layersJson)
        indexDatabingding.append("{\n")
        indexDatabingding.append("\"data\":{\n")
        indexDatabingding.append(indexData)
        indexDatabingding.append("}\n")
        indexDatabingding.append("}\n")

        indexJson.append("{\n")
        indexJson.append("\"id\":\"$id\",\n")
        indexJson.append("\"type\":\"$type\",\n")
        indexJson.append("\"layers\":[$layersJson]\n")
        indexJson.append("}\n")

        println(indexCss.toString())
        println(indexDatabingding.toString())
        println(indexJson.toString())
        println(data.toJSONString())

        val path = baseContext.filesDir.absolutePath + "/" + id
        FileUtil.saveToFile(baseContext, path, "index.css", indexCss.toString())
        FileUtil.saveToFile(
            baseContext,
            path,
            "index.databinding",
            indexDatabingding.toString()
        )
        FileUtil.saveToFile(baseContext, path, "gaixa-demo.json", indexJson.toString())
        var dataJson = JSONObject();
        dataJson["data"] = data;
        FileUtil.saveToFile(baseContext, path, "index.data", dataJson.toJSONString())
        val intent = Intent(ZQRCodeActivity@ this, ZDMTemplateActivity::class.java)
        intent.putExtra("templateId", id)
        startActivity(intent)
    }

    fun parseLayers(
        layers: JSONArray,
        indexCss: StringBuilder,
        indexDatabingding: StringBuilder,
        layersJson: StringBuilder
    ) {
        layers.forEachIndexed { index, element ->
            if (element is JSONObject) {
                val elementId = element.getString("id")
                var elementType = element.getString("type")
                if (elementType == "button") {
                    elementType = "text"
                }
                layersJson.append("{\n")
                if (element.contains("type")) {
                    layersJson.append("\"id\":\"$elementId\",\n")
                    layersJson.append("\"type\":\"$elementType\"")
                }
                if (element.contains("dataBinding")) {
                    val databinding = element.getJSONObject("dataBinding").getJSONObject("data")
                    if (!TextUtils.isEmpty(indexDatabingding)) {
                        indexDatabingding.append(",\n")
                    }
                    indexDatabingding.append("\"" + elementId + "\":" + databinding.toJSONString());
                }
                if (element.contains("styles")) {
                    indexCss.append("#$elementId{\n")
                    indexCss.append(element.getString("styles") + "\n")
                    indexCss.append("}\n")
                }
                if (element.contains("layers")) {
                    val layers = element.getJSONArray("layers")
                    layersJson.append(",\n\"layers\":[\n")
                    parseLayers(layers, indexCss, indexDatabingding, layersJson)
                    layersJson.append("]\n")
                }
                layersJson.append("}\n")
                if (index < layers.lastIndex) {
                    layersJson.append(",\n")
                }
            }
        }
    }

    override fun onScanResultFailure() {
        super.onScanResultFailure()
    }
}